import tkinter as tk
from tkinter import messagebox
import datetime
import subprocess
import threading
import time
from ui_components import create_main_ui
from task_manager import TaskManager
from config_manager import ConfigManager
from utils import format_time


class ShutdownTimerApp(tk.Frame):  # 继承自 tk.Frame
    def __init__(self, root):
        super().__init__(root)  # 调用父类构造函数
        self.root = root
        self.root.title("智能定时关机工具")
        self.root.geometry("450x650")
        self.root.resizable(False, False)

        # 将原来应用于 root 的配置改为应用于 self
        self.configure(bg="#f0f0f0")
        self.pack(fill=tk.BOTH, expand=True)

        # 设置中文字体
        self.font = ("Microsoft YaHei UI", 10)

        # 初始化组件
        self.task_manager = TaskManager()
        self.config_manager = ConfigManager()
        self.config = self.config_manager.load_config()

        # 关机状态变量
        self.shutdown_time = 0
        self.timer_running = False
        self.timer_id = None
        self.reminder_id = None
        self.reminder_count = 0
        self.delay_window = None
        self.monitor_thread = None
        self._stop_event = threading.Event()

        # 计划类型控制
        self.schedule_type = tk.StringVar(value="单次")

        # 每周选项
        self.weekdays = {
            "周一": tk.BooleanVar(value=self.config.get("weekdays", {}).get("周一", True)),
            "周二": tk.BooleanVar(value=self.config.get("weekdays", {}).get("周二", True)),
            "周三": tk.BooleanVar(value=self.config.get("weekdays", {}).get("周三", True)),
            "周四": tk.BooleanVar(value=self.config.get("weekdays", {}).get("周四", True)),
            "周五": tk.BooleanVar(value=self.config.get("weekdays", {}).get("周五", True)),
            "周六": tk.BooleanVar(value=self.config.get("weekdays", {}).get("周六", False)),
            "周日": tk.BooleanVar(value=self.config.get("weekdays", {}).get("周日", False)),
        }

        # 检查是否存在现有任务，并同步状态
        if self.task_manager.check_existing_task():
            self.timer_running = True
            self.status_var = tk.StringVar(value="检测到已有关机计划")
        else:
            self.timer_running = False
            self.status_var = tk.StringVar(value="就绪")

        # 定义UI回调方法
        self.update_schedule_ui = self._update_schedule_ui
        self.update_shutdown_ui = self._update_shutdown_ui
        self.show_shutdown_reminder = self._show_shutdown_reminder
        self.delay_shutdown = self._delay_shutdown
        self.force_shutdown = self._force_shutdown
        self.remind_set_shutdown = self._remind_set_shutdown

        # 创建界面
        create_main_ui(self)

        # 如果没有设置关机时间，5秒后提醒
        if not self.config.get("shutdown_time") and not self.timer_running:
            self.reminder_id = self.root.after(30000, self.remind_set_shutdown)

        # 启动任务监控线程
        self.start_task_monitor()

    def start_task_monitor(self):
        """启动后台线程监控计划任务状态"""
        if self.monitor_thread and self.monitor_thread.is_alive():
            return

        self._stop_event.clear()
        self.monitor_thread = threading.Thread(target=self._monitor_task, daemon=True)
        self.monitor_thread.start()

    def _monitor_task(self):
        """监控计划任务状态的后台线程函数"""
        while not self._stop_event.is_set():
            try:
                # 每5秒检查一次
                time.sleep(5)

                # 如果应用认为任务在运行，但实际任务不存在
                if self.timer_running and not self.task_manager.check_existing_task():
                    # 在主线程中执行UI更新
                    self.root.after(0, self._reset_state)
            except Exception as e:
                print(f"监控任务异常: {e}")

    def _reset_state(self):
        """重置应用状态"""
        if self.timer_id:
            self.root.after_cancel(self.timer_id)

        self.timer_running = False
        self.shutdown_time = 0
        self.countdown_var.set("00:00:00")
        self.status_var.set("就绪")

        # 清除配置中的关机时间
        self.config.pop("shutdown_time", None)
        self.config_manager.save_config(self.config)

        # 显示提示
        messagebox.showinfo("提示", "检测到关机计划已被取消，状态已重置")

    def destroy(self):
        """应用关闭时清理资源"""
        self._stop_event.set()
        if self.monitor_thread:
            self.monitor_thread.join(timeout=1.0)
        super().destroy()  # 调用父类的 destroy 方法


    def _update_schedule_ui(self):
        """更新计划类型UI显示"""
        if self.schedule_type.get() == "每周":
            self.weekly_frame.pack(fill=tk.X, pady=(0, 10), ipady=5)
        else:
            self.weekly_frame.pack_forget()

    def _update_shutdown_ui(self):
        """更新关机方式UI显示"""
        if self.shutdown_type.get() == "倒计时":
            self.countdown_frame.pack(fill=tk.X)
            self.specific_frame.pack_forget()
        else:
            self.countdown_frame.pack_forget()
            self.specific_frame.pack(fill=tk.X)

    def start_countdown(self):
        """开始关机倒计时"""
        # 强制检查并删除现有任务（避免残留）
        self.task_manager.delete_scheduled_task()
        self.timer_running = False  # 重置状态

        if self.timer_running:
            messagebox.showinfo("提示", "已有正在执行的关机计划")
            return

        try:
            if self.shutdown_type.get() == "倒计时":
                try:
                    hours = int(self.hours_var.get())
                    minutes = int(self.minutes_var.get())
                    seconds = int(self.seconds_var.get())
                except ValueError:
                    messagebox.showerror("错误", "请输入有效的数字")
                    return

                total_seconds = hours * 3600 + minutes * 60 + seconds

                if total_seconds <= 0:
                    messagebox.showerror("错误", "请设置大于0的时间")
                    return

                self.shutdown_time = total_seconds
                shutdown_datetime = datetime.datetime.now() + datetime.timedelta(seconds=total_seconds)
                self.status_var.set(f"系统将于 {shutdown_datetime.strftime('%H:%M:%S')} 关机")
            else:
                try:
                    hour = int(self.shutdown_hours_var.get())
                    minute = int(self.shutdown_minutes_var.get())
                except ValueError:
                    messagebox.showerror("错误", "请输入有效的数字")
                    return

                now = datetime.datetime.now()
                shutdown_datetime = now.replace(hour=hour, minute=minute, second=0, microsecond=0)

                # 如果设置的时间已经过去，则设置为明天
                if shutdown_datetime <= now:
                    shutdown_datetime += datetime.timedelta(days=1)

                self.shutdown_time = int((shutdown_datetime - now).total_seconds())
                self.status_var.set(f"系统将于 {shutdown_datetime.strftime('%H:%M:%S')} 关机")

            # 创建计划任务
            self.task_manager.create_scheduled_task(
                shutdown_datetime,
                self.schedule_type.get(),
                {day: var.get() for day, var in self.weekdays.items()}
            )

            self.timer_running = True

            # 保存配置
            self.config["shutdown_time"] = shutdown_datetime.strftime("%Y-%m-%d %H:%M:%S")
            self.config["schedule_type"] = self.schedule_type.get()
            self.config["weekdays"] = {day: var.get() for day, var in self.weekdays.items()}
            self.config_manager.save_config(self.config)

            # 启动倒计时更新
            self.update_countdown()

            # 显示成功消息
            messagebox.showinfo("成功", f"已设置{self.get_schedule_text()}关机计划")

            # 检查是否需要设置提醒
            if self.shutdown_time > 600:  # 10分钟 = 600秒
                self.root.after((self.shutdown_time - 600) * 1000, self.show_shutdown_reminder)

        except Exception as e:
            messagebox.showerror("错误", f"设置关机计划失败: {str(e)}")
            self.timer_running = False

    def get_schedule_text(self):
        """获取计划类型的文本描述"""
        if self.schedule_type.get() == "单次":
            return "单次"
        elif self.schedule_type.get() == "每天":
            return "每天"
        else:
            days = [day for day, var in self.weekdays.items() if var.get()]
            return f"每周{','.join(days)}"

    def update_countdown(self):
        """更新倒计时显示"""
        if not self.timer_running:
            return

        if self.shutdown_time > 0:
            self.shutdown_time -= 1
            self.countdown_var.set(format_time(self.shutdown_time))
            self.timer_id = self.root.after(1000, self.update_countdown)
        else:
            self.timer_running = False
            self.countdown_var.set("00:00:00")
            self.status_var.set("系统将立即关机")

    def cancel_shutdown(self):
        """取消关机计划"""
        # 强制检查状态
        if not self.timer_running and not self.task_manager.check_existing_task():
            messagebox.showinfo("提示", "当前没有进行中的关机计划")
            return

        try:
            # 关闭延迟窗口
            if self.delay_window and self.delay_window.winfo_exists():
                self.delay_window.destroy()

            # 取消系统关机命令
            try:
                subprocess.run(["shutdown", "/a"], check=True)
            except subprocess.CalledProcessError:
                pass

            # 删除计划任务
            self.task_manager.delete_scheduled_task()

            # 停止倒计时
            if self.timer_id:
                self.root.after_cancel(self.timer_id)

            # 彻底重置状态
            self.timer_running = False
            self.shutdown_time = 0
            self.countdown_var.set("00:00:00")
            self.status_var.set("就绪")

            # 清除配置中的关机时间
            self.config.pop("shutdown_time", None)
            self.config_manager.save_config(self.config)

            # 显示成功消息
            messagebox.showinfo("成功", "已取消所有关机计划")

        except Exception as e:
            messagebox.showerror("错误", f"取消关机计划失败: {str(e)}")

    def _show_shutdown_reminder(self):
        """显示关机提醒窗口"""
        if self.delay_window and self.delay_window.winfo_exists():
            return

        self.delay_window = tk.Toplevel(self.root)
        self.delay_window.title("即将关机")
        self.delay_window.geometry("340x370")
        self.delay_window.resizable(False, False)
        self.delay_window.configure(bg="#f0f0f0")
        self.delay_window.transient(self.root)
        self.delay_window.grab_set()

        # 计算当前关机时间
        current_shutdown_time = datetime.datetime.now() + datetime.timedelta(seconds=self.shutdown_time)

        # 显示提醒信息
        message = tk.Label(
            self.delay_window,
            text=f"系统将于{format_time(600)}后({current_shutdown_time.strftime('%H:%M:%S')})关机\n请选择操作：",
            font=(self.font[0], 12),
            bg="#f0f0f0",
            wraplength=300
        )
        message.pack(pady=20)

        # 延迟选项框架
        delay_frame = tk.Frame(self.delay_window, bg="#f0f0f0")
        delay_frame.pack(pady=15)

        # 延迟按钮
        delay_options = [0.5, 1, 1.5, 2]  # 小时
        for i, hours in enumerate(delay_options):
            btn = ttk.Button(
                delay_frame,
                text=f"延后{hours}小时",
                command=lambda h=hours: self.delay_shutdown(h),
                width=9,
                style="Accent.TButton"
            )
            btn.grid(row=0, column=i, padx=3)

        # 新增按钮行框架
        button_row = tk.Frame(self.delay_window, bg="#f0f0f0")
        button_row.pack(pady=15)

        # 保持原计划按钮
        keep_btn = ttk.Button(
            button_row,
            text="保持原计划",
            command=self.delay_window.destroy,
            width=15,
            style="Accent.TButton"
        )
        keep_btn.grid(row=0, column=0, padx=5)

        # 取消关机按钮
        cancel_btn = ttk.Button(
            button_row,
            text="取消关机",
            command=self.cancel_shutdown,
            width=15,
            style="Danger.TButton"
        )
        cancel_btn.grid(row=0, column=1, padx=5)

        # 强制关闭应用并关机按钮
        force_frame = tk.Frame(self.delay_window, bg="#f0f0f0")
        force_frame.pack(pady=10)

        force_btn = ttk.Button(
            force_frame,
            text="强制关闭所有应用并立即关机",
            command=self.force_shutdown,
            width=28,
            style="Danger.TButton"
        )
        force_btn.pack()

        # 调整窗口位置至屏幕中央
        self.delay_window.update_idletasks()
        width = self.delay_window.winfo_width()
        height = self.delay_window.winfo_height()
        x = (self.delay_window.winfo_screenwidth() // 2) - (width // 2)
        y = (self.delay_window.winfo_screenheight() // 2) - (height // 2)
        self.delay_window.geometry('{}x{}+{}+{}'.format(width, height, x, y))

    def _delay_shutdown(self, hours):
        """延迟关机时间"""
        if not self.timer_running:
            return

        try:
            # 关闭延迟窗口
            if self.delay_window and self.delay_window.winfo_exists():
                self.delay_window.destroy()

            # 取消原有关机命令
            try:
                subprocess.run(["shutdown", "/a"], check=True)
            except subprocess.CalledProcessError:
                pass

            # 计算新的关机时间
            delay_seconds = int(hours * 3600)
            new_shutdown_datetime = datetime.datetime.now() + datetime.timedelta(seconds=delay_seconds)

            # 更新关机时间
            self.shutdown_time = delay_seconds
            self.status_var.set(f"系统将于 {new_shutdown_datetime.strftime('%H:%M:%S')} 关机")

            # 删除旧任务
            self.task_manager.delete_scheduled_task()

            # 创建新的单次任务
            self.task_manager.create_scheduled_task(new_shutdown_datetime, "单次", {})

            # 更新配置
            self.config["shutdown_time"] = new_shutdown_datetime.strftime("%Y-%m-%d %H:%M:%S")
            self.config["schedule_type"] = "单次"
            self.config_manager.save_config(self.config)

            # 显示延迟成功消息
            messagebox.showinfo("成功", f"已将关机时间延后{hours}小时")

            # 重新开始倒计时
            if self.timer_id:
                self.root.after_cancel(self.timer_id)
            self.update_countdown()

        except Exception as e:
            messagebox.showerror("错误", f"设置延迟关机失败: {str(e)}")

    def _force_shutdown(self):
        """强制关闭所有应用并立即关机"""
        try:
            # 关闭延迟窗口
            if self.delay_window and self.delay_window.winfo_exists():
                self.delay_window.destroy()

            # 停止倒计时
            if self.timer_id:
                self.root.after_cancel(self.timer_id)

            # 尝试优雅地关闭应用程序
            self.status_var.set("正在关闭应用程序...")
            self.root.update()  # 更新UI显示

            # 使用taskkill命令强制终止所有非系统进程
            subprocess.run(["taskkill", "/F", "/FI", "USERNAME eq " + os.getlogin(), "/T"], shell=True)

            # 短暂等待应用关闭
            time.sleep(2)

            # 执行关机命令
            self.status_var.set("正在关机...")
            self.root.update()
            subprocess.run(["shutdown", "/s", "/t", "0"], check=True)

        except Exception as e:
            messagebox.showerror("错误", f"强制关机失败: {str(e)}")
        finally:
            # 清除配置中的关机时间
            self.config.pop("shutdown_time", None)
            self.config_manager.save_config(self.config)

    def _remind_set_shutdown(self):
        """提醒用户设置关机时间"""
        if not self.timer_running and self.reminder_count <= 10:  # 只提醒10次
            self.reminder_count += 1
            messagebox.showinfo("提醒", "请设置关机时间！")

        # 无论用户是否设置了关机时间，都继续计时
        if not self.timer_running and self.reminder_count <= 10:
            self.reminder_id = self.root.after(30000, self.remind_set_shutdown)
        else:
            self.reminder_id = None